﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;

namespace SoftVenture.Sharepoint.Permissions
{
    public class FileHelper
    {
        SPWeb web;
        SPFolder folder;
        string fileName;

        private bool _RoleInheritance = false;
        public  bool RoleInheritance 
        { 
            get
            {
                return _RoleInheritance;
            }
            set
            {
                _RoleInheritance = value;
            }
        }

        public FileHelper(string url, string docLib)
        {
            Context(url);

            this.folder = web.Folders[docLib];
        }
        public FileHelper(string url, string docLib, string fileName)
        {
            Context(url);

            this.folder = web.Folders[docLib];

            this.fileName = fileName;
        }

        private void Context(string url)
        {
            SPSecurity.RunWithElevatedPrivileges(
                delegate()
                {
                    using (SPSite elevatedSite = new SPSite(url))
                    {
                        this.web = elevatedSite.OpenWeb();
                    }
                }
            );
        }

        public int List(bool showAll, ref string output)
        {
            
            foreach (SPFile f in folder.Files)
                if (string.IsNullOrEmpty(this.fileName) || (!string.IsNullOrEmpty(this.fileName) && f.Name == this.fileName))
                {
                    output += f.Name + Environment.NewLine;

                    if (showAll || f.Item.HasUniqueRoleAssignments)
                        foreach (SPRoleAssignment role in f.Item.RoleAssignments)
                        {
                            output += "\t" + role.Member.Name + Environment.NewLine;
                            foreach (SPRoleDefinition def in role.RoleDefinitionBindings)
                                if( showAll || !def.Hidden)
                                    output += "\t\t" + def.Name + Environment.NewLine;
                        }
                                
                    else
                        output += "\tParent Inheritance" + Environment.NewLine;
                }

            return 0;
        }

        public int Add(string roleName, string user, ref string output)
        {
            #region Input Test
            if (string.IsNullOrEmpty(roleName))
            {
                output += "Role Name not set!";
                return -1;
            }

            if (string.IsNullOrEmpty(user))
            {
                output += "user not set!";
                return -1;
            }

            if (web == null)
            {
                output += "Web not set!";
                return -1;
            }

            if (folder == null)
            {
                output += "Folder not set!";
                return -1;
            }
            #endregion
            web.AllowUnsafeUpdates = true;

            SPRoleAssignment roleAssignment = BuildRoleAssignment(roleName, user);

            foreach (SPFile f in folder.Files)
                if (string.IsNullOrEmpty(this.fileName) || (!string.IsNullOrEmpty(this.fileName) && f.Name == this.fileName))
                        f.Item.RoleAssignments.Add(roleAssignment);

            web.Update();
            
            return 0;
        }
        public int Remove(string roleName, string user, ref string output)
        {
            web.AllowUnsafeUpdates = true;

            SPRoleAssignment roleAssignment = BuildRoleAssignment(user);

            foreach(SPFile f in folder.Files)
                if (string.IsNullOrEmpty(this.fileName) || (!string.IsNullOrEmpty(this.fileName) && f.Name == this.fileName))
                {
                    foreach (SPRoleAssignment role in f.Item.RoleAssignments)
                    {
                        if (role.Member.Name == user)
                        {
                            output += string.Format("Removing {0} of the user {1} from file {2}.", roleName, user, f.Name);
                            roleAssignment.RoleDefinitionBindings.Add(this.web.RoleDefinitions[roleName]);
                            role.RoleDefinitionBindings.Remove(roleAssignment.RoleDefinitionBindings[0]);
                            role.Update();
                        }
                    }
                }

            web.Update();
            return 0;
        }

        public int RemoveAll(string user, ref string output)
        {
            web.AllowUnsafeUpdates = true;

            foreach (SPFile f in folder.Files)
                if (string.IsNullOrEmpty(this.fileName) || (!string.IsNullOrEmpty(this.fileName) && f.Name == this.fileName))
                    foreach (SPRoleAssignment role in f.Item.RoleAssignments)
                    {
                        if (role.Member.Name == user)
                        {
                            output += string.Format("Removing all roles of the user {0} from file {1}.", user, f.Name);
                            role.RoleDefinitionBindings.RemoveAll();
                            role.Update();
                        }
                    }

            web.Update();
            return 0;
        }
        public int ResetRoleInheritance(ref string output)
        {
            web.AllowUnsafeUpdates = true;

           foreach (SPFile f in folder.Files)
               if (string.IsNullOrEmpty(this.fileName) || (!string.IsNullOrEmpty(this.fileName) && f.Name == this.fileName) && f.Item.HasUniqueRoleAssignments)
                {
                    output += string.Format("Reseting roles inheritance from file {0}.", f.Name);
                    f.Item.ResetRoleInheritance();
                    f.Item.Update();
                }

            web.Update();
            return 0;
        }
        public int BreakRoleInheritance(ref string output)
        {
            foreach (SPFile f in folder.Files)
                if (string.IsNullOrEmpty(this.fileName) || (!string.IsNullOrEmpty(this.fileName) && f.Name == this.fileName) && !f.Item.HasUniqueRoleAssignments)
                {
                    output += string.Format("Breaking roles inheritance from file {0}.", f.Name);
                    f.Item.BreakRoleInheritance(RoleInheritance);
                    f.Item.Update();
                }

            return 0;
        }
        private SPRoleAssignment BuildRoleAssignment(string user)
        {
            SPRoleAssignment roleAssignment = null;

            try
            {
                roleAssignment = new SPRoleAssignment(this.web.SiteGroups[user]);
            }
            catch (Exception)
            {
                roleAssignment =
                 new SPRoleAssignment(
                     user,
                     string.Empty,
                     string.Empty,
                     string.Empty);
            }

            return roleAssignment;
        }
        
        private SPRoleAssignment BuildRoleAssignment(string roleName, string user)
        {
            SPRoleAssignment roleAssignment = null;
            SPRoleDefinition roleDef = this.web.RoleDefinitions[roleName];

            try
            {
                SPGroup group = web.SiteGroups[user];

                roleAssignment = new SPRoleAssignment(group);

            }
            catch (Exception)
            {
                roleAssignment =
                 new SPRoleAssignment(
                     user,
                     string.Empty,
                     string.Empty,
                     string.Empty);
            }

            roleAssignment.RoleDefinitionBindings.Add(roleDef);

            return roleAssignment;
        }

        public void Dispose()
        {
            if (this.web != null)
            {
                this.web.Close();
                this.web.Dispose();
            }
        }
    }
}
